//----------------------------------------------------------------------------
// date.cpp
//
// display dialog allowing date input
//
// Copyright (C) 2011 Neil Butterworth
//----------------------------------------------------------------------------

#include <windows.h>
#include <commctrl.h>
#include <string>
#include <iostream>
#include <iomanip>
#include "command.h"
#include "cmdline.h"
#include "util.h"
#include "resource.h"
#include "error.h"

using namespace std;

namespace Swine {

//----------------------------------------------------------------------------
// Command & option names
//----------------------------------------------------------------------------

const char * const DATE_CMD 		= "date";
const char * const CAPTION_OPT 		= "caption";
const char * const TEXT_OPT 		= "text";
const char * const ISO_OPT 			= "iso";

//----------------------------------------------------------------------------
// Help
//----------------------------------------------------------------------------

const char * const DATE_HELP =
	"display date picker\n"
	"options:\n"
	" --caption     specify message box caption (default is 'Enter date') \n"
	" --text        specify initial date in YYYYMMDD format (default is today)"
	" --iso         output date in YYYYMMDD format \n";


//----------------------------------------------------------------------------
// Command class and registration
//----------------------------------------------------------------------------

class DateCmd : public Command {

	public:

		DateCmd() : Command( DATE_CMD, DATE_HELP ), mDoISO( false ) {}

		BOOL ProcessControlMessages( HWND wnd, int ctrl, int msg ) const;
		int Execute( CmdLine & cl ) const;
		void InitDialog( HWND dlg, CmdLine & cl  ) const;

	private:

		void SetDate( HWND dlg, const string & ds ) const;
		string FormatDate( HWND dlg ) const;
		mutable bool mDoISO;
};

static AddCommand <DateCmd> cmd1_;

//----------------------------------------------------------------------------
// Handle WM_COMMAND messages - we are only interested in button clicks
//----------------------------------------------------------------------------

BOOL DateCmd :: ProcessControlMessages( HWND hwnd, int ctrl, int msg ) const {

	if ( ctrl == IDCANCEL && msg == BN_CLICKED ) {
		Reply( "cancel" );
		DestroyWindow( hwnd );
		return TRUE;
	}
	else if ( ctrl == IDOK && msg == BN_CLICKED ) {
		if ( ! mDoISO  ) {
			Reply( TextFromCtrl( hwnd, IDC_DATETIMEPICKER  ) );
		}
		else {
			Reply( FormatDate( hwnd ) );
		}
		DestroyWindow( hwnd );
		return TRUE;
	}
	else {
		return TRUE;
	}
}

//----------------------------------------------------------------------------
// Format date for output
//----------------------------------------------------------------------------

string DateCmd :: FormatDate( HWND dlg ) const {
	SYSTEMTIME st;
	DateTime_GetSystemtime( MustGetControl( dlg, IDC_DATETIMEPICKER ), & st );
	ostringstream os;
	os << setw(4) << st.wYear
			<< setw(2) << setfill( '0' ) << st.wMonth
			<< setw(2) << setfill( '0' ) << st.wDay;
	return os.str();
}

//----------------------------------------------------------------------------

int DateCmd :: Execute( CmdLine & cl ) const {
	DoDialog( IDD_DATE, cl );
	return 0;
}

//----------------------------------------------------------------------------
// Set the date for the picker. Possibly should do more checking of
// the date's validity.
//----------------------------------------------------------------------------

void DateCmd :: SetDate( HWND dlg, const string & date ) const {
	if ( date.size() != 8 ) {
		throw Error( "Date must be in YYYYMMDD format" );
	}
	string ys = date.substr( 0, 4 );
	string ms = date.substr( 4, 2);
	string ds = date.substr( 6, 2 );

	int d, m, y;
	if ( ! ToType( ys, y ) ) {
		throw Error( "Invalid year: " + ys );
	}
	if ( ! ToType( ms, m ) ) {
		throw Error( "Invalid month: " + ms );
	}
	if ( ! ToType( ds, d ) ) {
		throw Error( "Invalid day: " + ds );
	}
	SYSTEMTIME st;
	memset( &st, 0, sizeof( st ) );
	st.wDay = d;
	st.wMonth = m;
	st.wYear = y;
	DateTime_SetSystemtime( MustGetControl( dlg, IDC_DATETIMEPICKER ), GDT_VALID, & st );
}

//----------------------------------------------------------------------------
// Initialise, possibly setting date
//----------------------------------------------------------------------------

void DateCmd :: InitDialog( HWND dlg, CmdLine & cl ) const {
	string caption = cl.ExtractOption( CAPTION_OPT, "Enter Date" );
	string date = cl.ExtractOption( TEXT_OPT, "" );
	mDoISO = cl.ExtractOption( ISO_OPT );
	cl.MustBeEmpty();
	SetWindowText( dlg, caption.c_str() );
	if ( date != "" ) {
		SetDate( dlg, date );
	}
}


//----------------------------------------------------------------------------

} // namespace
